package com.yeziji.dynamicConfig.base;

import cn.hutool.core.util.StrUtil;
import com.yeziji.common.CommonSymbol;
import com.yeziji.constant.VariousStrPool;
import com.yeziji.dynamicConfig.controller.vo.ConfigMetaVO;
import com.yeziji.dynamicConfig.msg.DynamicConfigErrorMsg;
import com.yeziji.utils.expansion.Asserts;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.origin.OriginTrackedValue;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * config 属性
 *
 * @author hwy
 * @since 2023/12/13 10:15
 **/
@Slf4j
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ConfigMeta {
    private final Pattern ENV_PATTERN = Pattern.compile("\\[([^\\]]+)\\]");

    /**
     * 配置文件名称
     */
    @NotBlank(message = "环境不能为空", groups = {Update.class, Delete.class})
    private String env;

    /**
     * 配置键值
     */
    @NotBlank(message = "配置键值不能为空", groups = {Update.class, Delete.class, ConfigurationUpdate.class})
    private String key;

    /**
     * 配置值
     */
    @NotNull(message = "配置值不能为空", groups = {Update.class})
    private Object value;

    /**
     * 配置键值对象
     */
    @NotNull(message = "配置值不能为空", groups = {ConfigurationUpdate.class})
    private Map<String, Object> properties;

    public ConfigMeta(String env, String key, Object value) {
        this.env = env;
        this.key = key;
        this.value = value;
    }

    /**
     * 转 vo
     */
    public ConfigMetaVO convertToVo() {
        Asserts.notNull(this, DynamicConfigErrorMsg.CONFIG_IS_NOT_EXISTS);
        return ConfigMetaVO.builder()
                .key(key)
                .env(this.getEnvStr())
                .value(this.convertObjVal())
                .build();
    }

    /**
     * obj 可能对应不同的 source properties，这里目前应该只用到 OriginTrackedValue 所以单独处理该类
     */
    public Object convertObjVal() {
        if (this.value instanceof OriginTrackedValue) {
            return ((OriginTrackedValue) this.value).getValue();
        }
        return this.value;
    }

    /**
     * 将 spring properties name xxx [xxx] 转换为对应的环境字符串
     */
    public String getEnvStr() {
        Matcher matcher = ENV_PATTERN.matcher(this.env);
        String env = matcher.find() ? matcher.group(1) : this.env;
        if (StrUtil.isNotBlank(env) && env.startsWith(VariousStrPool.Dictionary.APPLICATION)) {
            String replaceStr = env.replace(VariousStrPool.Dictionary.APPLICATION, VariousStrPool.EMPTY);
            int dotIndex = replaceStr.indexOf(CommonSymbol.FULL_STOP);
            if (dotIndex == 0) {
                env = VariousStrPool.Dictionary.DEFAULT;
            } else {
                try {
                    env = replaceStr.substring(1, dotIndex);
                } catch (Exception e) {
                    log.error("轉換異常: {}", this.env, e);
                    env = VariousStrPool.Dictionary.UNKNOWN;
                }
            }
        }
        return env;
    }

    public interface Update{}

    public interface Delete{}

    public interface ConfigurationUpdate {
    }
}
